package Server.players;
import java.util.TreeMap;

import common.exception.ExtinctionException;


public class Species<DinoType extends Dino>{

	public static final int MAX_NUMBER_OF_DINO = 100;
	private String myName;
	private TreeMap<Integer, DinoType> dinos;
	private int age;
	
	public Species(String name){
		this.myName = name;
		this.dinos = new TreeMap<Integer, DinoType>();
		this.age = 1;
	}
	
	// @ensures this == s
	public Species(Species<DinoType> s){
		this.myName = s.myName;
		this.dinos = new TreeMap<Integer, DinoType>();
		this.dinos.putAll(s.dinos);
		this.age = s.age;
	}
	
	// @ensures \result == this.getName()
	@Override
	public String toString(){
		return this.myName;
	}
	@Override
	public int hashCode() {
		return 31 * this.myName.hashCode();
	}
	
	// @ensures (\result == true) <==> (this == o)
	@Override
	public boolean equals(Object o){
		if (o instanceof Species<?>){
			Species<?> s = (Species<?>) o;
			
			if (this.myName.equals(s.getName()) &&
				this.age == s.getAge() &&
				this.dinos.equals(s.dinos))
				return true;
		}
		
		return false;
	}
	
	public String getName(){
		return this.myName;
	}
	public int getAge(){
		return this.age;
	}
	
	/*
	 * @ensures (forall int i;i < \result.length;this.get(\result[i]) != null)
	 */
	public Integer[] getDinoList(){
		return this.dinos.keySet().toArray(new Integer[this.dinos.size()]);
	}

	public char getType() {
		try{
			if (this.dinos.firstEntry().getValue().isCarniv()){
				return 'c';
			}
			
			return 'e';
		} catch (NullPointerException e){
			throw new RuntimeException();
		}
	}
	
	public int count() {
		return this.dinos.size();
	}

	/*
	 * @ensures \result != null ==> (* la specie possiede il dinosauro con id idDino *)
	 */
	public DinoType get(int idDino) {
		try{
			return this.dinos.get(idDino);
		} catch (NullPointerException e){
			return null;
		}
		
	}
	
	/*
	 * @ensures this.getAge > \old(this.getAge)
	 * @signals (ExtinctionException) this.getAge >= 120
	 */
	public void older() throws ExtinctionException{
		if (this.age >= 120)
			throw new ExtinctionException();
		
		this.age++;
	}
	
	/*
	 * @ensures (\forall int i;i > 0;this.get(i) != null ==> (* Il dinosauro aumenta l'età *)
	 */
	public void updateDinosAge(){
		for (Dino d : this.dinos.values()){
			d.older();
		}
	}
	
	/*
	 * @requires dino != null
	 * @ensures this.count() == \old(this.count()) + 1 &&
	 * this.get(dino.getId()) != null
	 */
	public void addDino(DinoType dino){
		int id = ((Dino)dino).getId();
		this.dinos.put(id, dino);
	}

	/*
	 * @requires dino != null
	 * @ensures this.count() == \old(this.count()) - 1 &&
	 * this.get(dino.getId()) == null
	 */
	public void remove(DinoType dino) {
		int id = dino.getId();
		this.dinos.remove(id);
	}
}
